package com.woniu.shops.service.imp;

import com.woniu.common.CustomException.UserException;
import com.woniu.common.pojo.Order;
import com.woniu.common.pojo.Shops;
import com.woniu.common.vo.OrderAggregate;
import com.woniu.shops.mapper.OrderMapper;
import com.woniu.shops.service.OrdersService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Service
public class OrdersServiceImp implements OrdersService {
    @Resource
    private OrderMapper orderMapper;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;



    @Override
    public List<Order> getOrder(Shops shops) {
        if (shops != null) {
            List<Order> orderList = (List<Order>) redisTemplate.opsForValue().get("order" + shops.getSname());
            if (orderList != null) {
                for (Order order : orderList) {
                    IndexQuery indexQuery = new IndexQueryBuilder()
                            .withId(order.getOid())
                            .withObject(new OrderAggregate(order.getOid(), Arrays.asList(order)))
                            .build();
                    elasticsearchRestTemplate.index(indexQuery, IndexCoordinates.of("order"));
                }
                return orderList;
            }
            List<Order> orders = orderMapper.getOrder(shops);
            if (orders != null) {
                for (Order order : orders) {
                    IndexQuery indexQuery = new IndexQueryBuilder()
                            .withId(order.getOid())
                            .withObject(new OrderAggregate(order.getOid(), Arrays.asList(order)))
                            .build();
                    elasticsearchRestTemplate.index(indexQuery, IndexCoordinates.of("order"));
                }
                redisTemplate.opsForValue().set("order" + shops.getSname(), orders);
            }
            return orders;
        }
        throw new RuntimeException("不好意思,参数有误");
    }

    @Override
    public void updateOrder(Order order) {
        if(order != null){
            Integer i = orderMapper.updateOrder(order);
            if(i > 0){
                redisTemplate.delete("order"+order.getShops().getSname()+"");
                elasticsearchRestTemplate.delete(order);
                return;
            }
            throw new UserException("不好意思,未知异常");
        }
        throw  new RuntimeException("不好意思,参数有误");
    }

    @Override
    public void deleteOrder(Order order) {
        if(order != null){
            Integer i = orderMapper.deleteOrder(order);
            if(i > 0){
                redisTemplate.delete("order"+order.getShops().getSname()+"");
                return;
            }
            throw new UserException("不好意思,未知异常");
        }
        throw  new RuntimeException("不好意思,参数有误");
    }

    @Override
    public void deleteOrders(Integer[] selectedOrderIds, Shops obj) {
        if(selectedOrderIds != null){
            Integer i = orderMapper.deleteOrders(selectedOrderIds);
            if(i == selectedOrderIds.length){
                redisTemplate.delete("order"+obj.getSname()+"");
                return;
            }
            throw new UserException("未知错误");
        }
        throw  new UserException("不好意思,数据有误");
    }

    @Override
    public List<Order> getOrders(Order order) {
        NativeSearchQuery query = null;
        if(order == null){
            throw new UserException("不好意思,输入有误");
        }
        if(order.getUser().getUsername() != null && !"".equals(order.getUser().getUsername()) && (order.getAddress() == null || "".equals(order.getAddress()))){
            query = new NativeSearchQueryBuilder()
                    .withQuery(QueryBuilders.matchQuery("user.username",order.getUser().getUsername())).build();
            //2. 查询
        }else if (order.getAddress() != null && !order.getAddress().isEmpty() && (order.getUser().getUsername() == null || order.getUser().getUsername().isEmpty())) {
            query = new NativeSearchQueryBuilder()
                    .withQuery(QueryBuilders.matchQuery("address", order.getAddress())).build();
            // 2. 执行查询
        }else if(order.getAddress() != null && order.getUser().getUsername() != null){
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            List<QueryBuilder> mustList = boolQueryBuilder.must();
            mustList.add(QueryBuilders.matchQuery("user.username",order.getUser().getUsername()));
            mustList.add(QueryBuilders.matchQuery("address", order.getAddress()));
            query = new NativeSearchQueryBuilder()
                    .withQuery(boolQueryBuilder).build();
        }
        //2. 查询
        SearchHits<Order> searchHits = elasticsearchRestTemplate.search(query, Order.class);
        //3. 迭代或者遍历
        searchHits.forEach(searchHit -> System.out.println(searchHit.getContent()));
        List<SearchHit<Order>> list = searchHits.toList();
        List<Order> orders = new ArrayList<>();
        for (SearchHit<Order> searchHit : list) {
            orders.add(searchHit.getContent());
        }
        return orders;
    }

    @Override
    public void Flusheds(Shops shops) {
        redisTemplate.delete("order"+shops.getSname()+"");
        List<Order> orders = orderMapper.getOrder(shops);
        if (orders != null) {
            for (Order order : orders) {
                elasticsearchRestTemplate.save(order);
            }
            redisTemplate.opsForValue().set("order" + shops.getSname(), orders);
        }
    }


}
